package easier.paging3;

import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.paging.CombinedLoadStates;
import androidx.paging.LoadState.Error;
import androidx.paging.LoadState.Loading;
import androidx.paging.LoadState.NotLoading;
import androidx.paging.LoadStateAdapter;
import androidx.paging.PagingDataAdapter;
import androidx.recyclerview.widget.ConcatAdapter;
import androidx.recyclerview.widget.DiffUtil.ItemCallback;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;

/**
 * 一个辅助工具类,使用RecyclerView SwipeRefreshLayout ViewStub ViewStub 创建一个界面,
 * recycler展示数据,
 * SwipeRefreshLayout下拉刷新,
 * {@link #createFooter()}上拉加载,
 * 两个viewStub展示空数据界面,网络异常界面
 *
 * @param <T> 数据类型
 */
public abstract class Paging3RefreshAdapter< T > extends Paging3Adapter< T > {

    /**
     * 展示数据
     */
    private final RecyclerView mRecycler;
    /**
     * 下拉树新
     */
    private final SwipeRefreshLayout mRefresh;

    /**
     * @param owner    创建{@link PagingDataAdapter}
     * @param recycler 展示数据
     * @param refresh  下拉刷新
     */
    public Paging3RefreshAdapter(
        ViewModelStoreOwner owner,
        ItemCallback< T > itemCallback,
        RecyclerView recycler,
        SwipeRefreshLayout refresh ) {

        super( owner, itemCallback );

        mRecycler = recycler;
        mRefresh = refresh;
    }

    /**
     * 构建view的行为:
     * 下拉树新:刷新数据
     * 页脚:加载更多
     * 第一次加载:展示下拉刷新
     * 没有数据展示空界面
     * 网络异常展示异常界面
     *
     * @param lifecycle 绑定生命
     */
    public void build( @NonNull Lifecycle lifecycle ) {

        LoadStateAdapter< ? > footer = createFooter();
        ConcatAdapter concatAdapter = withLoadStateFooter( footer );
        mRecycler.setAdapter( concatAdapter );

        addLoadStateListener( new Function1< CombinedLoadStates, Unit >() {
            @Override
            public Unit invoke( CombinedLoadStates combinedLoadStates ) {

                /* 第一次加载,如果没有刷新,显示刷新图标 */
                if ( combinedLoadStates.getRefresh() instanceof Loading ) {
                    if ( !mRefresh.isRefreshing() ) {
                        mRefresh.setRefreshing( true );
                    }
                }

                /* 第一次加载,加载完成,关闭刷新图标 */
                if ( combinedLoadStates.getRefresh() instanceof NotLoading ) {
                    if ( mRefresh.isRefreshing() ) {
                        mRefresh.setRefreshing( false );
                    }

                    int itemCount = getItemCount();
                    /* 首次加载完有没有数据 */
                    notifyNotLoadingResult( itemCount );
                }

                if ( combinedLoadStates.getRefresh() instanceof Error ) {

                    if ( mRefresh.isRefreshing() ) {
                        mRefresh.setRefreshing( false );
                    }

                    Throwable error = ((Error) combinedLoadStates.getRefresh()).getError();
                    notifyError( error );
                }

                if ( combinedLoadStates.getAppend() instanceof Error ) {

                    Throwable error = ((Error) combinedLoadStates.getAppend()).getError();
                    notifyError( error );
                }
                return null;
            }
        } );

        mRefresh.setOnRefreshListener( new OnRefreshListener() {
            @Override
            public void onRefresh() {

                retryOrRefresh();
            }
        } );

        mRefresh.setRefreshing( true );
        submitData( lifecycle );
    }

    /**
     * @return 创建页脚
     */
    @NonNull
    protected abstract LoadStateAdapter< ? > createFooter();

    /**
     * 根据数据量决定使用{@link PagingDataAdapter#refresh()}或者{@link PagingDataAdapter#retry()}
     */
    protected void retryOrRefresh() {

        if ( getItemCount() == 0 ) {
            retry();
        } else {
            refresh();
        }
    }

    /**
     * @param count 通知加载结果
     */
    protected void notifyNotLoadingResult( int count ) {

    }
}
